package com.loyalove.demo.kotlinboot.configuration

import com.loyalove.demo.kotlinboot.model.SequenceId
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.mongodb.core.FindAndModifyOptions
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import org.springframework.data.mongodb.core.query.isEqualTo
import org.springframework.stereotype.Component
import org.springframework.util.ReflectionUtils
import javax.persistence.GeneratedValue

@Component
class SaveMongoEventListener : AbstractMongoEventListener<Any>() {
    @Autowired
    lateinit var mongoTemplate: MongoTemplate

    override fun onBeforeConvert(event: BeforeConvertEvent<Any>) {
        val source = event.source
        ReflectionUtils.doWithFields(source.javaClass) { field ->
            ReflectionUtils.makeAccessible(field)
            if (field.isAnnotationPresent(GeneratedValue::class.java)) {
                //设置自增ID
                if (field.getLong(source)==0L) {
                    field.set(source, getNextId(source.javaClass.simpleName))
                }
            }
        }
    }

    /**
     * 获取下一个自增ID
     * @author yinjihuan
     * @param collName  集合名
     * @return
     */
    private fun getNextId(collName: String): Long? {
        val query = Query(Criteria.where("coll_name").isEqualTo(collName))
        val update = Update()
        update.inc("seq_id", 1)
        val options = FindAndModifyOptions()
        options.upsert(true)
        options.returnNew(true)
        val sequence = mongoTemplate.findAndModify(query, update, options, SequenceId::class.java)
        return sequence?.seqId
    }

}